import tnx from '@/tnx.js';
import {parse as parseJava} from 'java-parser';
import EntityClass from '../entity/EntityClass.js';
import EnumClass from '../entity/EnumClass.js';
import EnumConstant from '../entity/EnumConstant.js';
import ClassProperty from '../entity/ClassProperty.js';
import DomainProperty from '../entity/DomainProperty.js';
import EntityProperty from '../entity/EntityProperty.js';
import TypeKind from '../enums/TypeKind.js';
import BaseType from '../entity/BaseType.js';
import BaseClass from '../entity/BaseClass.js';
import ValueClass from '../entity/ValueClass.js';
import PlainClass from '../entity/PlainClass.js';
import GenericType from '../entity/GenericType.js';
import ConverterClass from '../entity/ConverterClass.js';

const javaLangClassNames = ['Boolean', 'Byte', 'Character', 'Class', 'Double', 'Error', 'Exception', 'Float',
    'Integer', 'Long', 'Number', 'Object', 'Short', 'String', 'StringBuffer', 'StringBuilder', 'Void', 'Enum'];

const arraySuffix = '[]';

/**
 * 代码解析工具
 */
export default {

    // 后续Java类源代码有变动时，可能解析会失败，需同步调整适配
    loadJavaClass(lib, filePath, code, predicate) {
        let index = filePath.lastIndexOf('/');
        let packageName = filePath.substring(0, index).replaceAll('/', '.');
        let simpleName = filePath.substring(index + 1, filePath.length - '.java'.length);

        const getImplementInterfaceSimpleNames = function (classElement) {
            let interfaceSimpleNames = [];
            if (classElement.classImplements) {
                let interfaceTypes = classElement.classImplements[0].children
                    .interfaceTypeList[0].children.interfaceType;
                for (let interfaceType of interfaceTypes) {
                    interfaceSimpleNames.push(interfaceType.children.classType[0].children.Identifier[0].image);
                }
            }
            return interfaceSimpleNames;
        }

        const getTypeSimpleName = function (typeElement) {
            if (typeElement.referenceType) {
                let classOrInterfaceTypeElement = typeElement.referenceType[0].children.classOrInterfaceType[0].children;
                let typeKey = Object.keys(classOrInterfaceTypeElement).find(key => key.endsWith('Type'));
                return classOrInterfaceTypeElement[typeKey][0].children.Identifier[0].image;
            }
            let typeElementChildren = typeElement.unannType[0].children;
            if (typeElementChildren.unannReferenceType) {
                let referenceTypeElement = typeElementChildren.unannReferenceType[0].children;
                let classTypeElement = referenceTypeElement.unannClassOrInterfaceType[0].children.unannClassType[0].children;
                let typeName = classTypeElement.Identifier[0].image;
                // 先判断泛型
                if (classTypeElement.typeArguments) {
                    let genericTypes = [];
                    let typeArgumentElements = classTypeElement.typeArguments[0].children
                        .typeArgumentList[0].children.typeArgument;
                    for (let typeArgumentElement of typeArgumentElements) {
                        let genericType;
                        let wildcardElement = typeArgumentElement.children.wildcard;
                        if (wildcardElement) {
                            genericType = wildcardElement[0].children.QuestionMark[0].image;
                            if (wildcardElement[0].children.wildcardBounds) {
                                let wildcardBoundsElement = wildcardElement[0].children.wildcardBounds[0].children;
                                if (wildcardBoundsElement.Extends) {
                                    genericType += ' extends ';
                                } else if (wildcardBoundsElement.Super) {
                                    genericType += ' super ';
                                }
                                genericType += getTypeSimpleName(wildcardBoundsElement);
                            }
                        } else if (typeArgumentElement.children.referenceType) {
                            genericType = getTypeSimpleName(typeArgumentElement.children);
                        }
                        if (genericType) {
                            genericTypes.push(genericType);
                        }
                    }
                    typeName += '<' + genericTypes.join(',') + '>';
                }
                // 再判断数组
                if (referenceTypeElement.dims) {
                    typeName += arraySuffix.repeat(referenceTypeElement.dims.length);
                }
                return typeName;
            } else if (typeElementChildren.unannPrimitiveTypeWithOptionalDimsSuffix) {
                let primitiveTypeElement = typeElementChildren.unannPrimitiveTypeWithOptionalDimsSuffix[0].children;
                let children = primitiveTypeElement.unannPrimitiveType[0].children;
                let key = Object.keys(children)[0];
                let typeName = children[key][0].image;
                while (!typeName) {
                    children = children[key][0].children;
                    key = Object.keys(children)[0];
                    typeName = children[key][0].image;
                }
                // 数组维度判断
                if (primitiveTypeElement.dims) {
                    typeName += arraySuffix.repeat(primitiveTypeElement.dims.length);
                }
                return typeName;
            }
            console.warn('Unable to get type:\n' + typeElement);
            return '';
        }

        const getImportClassName = function (code, typeName) {
            if (typeName) {
                // 考虑数组的情况
                if (typeName.endsWith(arraySuffix)) {
                    typeName = typeName.substring(0, typeName.length - arraySuffix.length);
                }
                // Java原生类型无需查找import
                if (typeName === typeName.toLowerCase()) {
                    return typeName;
                }
                // 判断是否已是import的完整类名
                if (typeName.contains('.') && code.contains(`import ${typeName};`)) {
                    return typeName;
                }
                // 此时typeName是简名

                // 内部类只需import主类
                let index = typeName.indexOf('.');
                let importSimpleName = index > 0 ? typeName.substring(0, index) : typeName;
                let importLines = code.match(new RegExp('import [a-zA-Z0-9_.]+\\.' + importSimpleName + ';', 'g'));
                if (importLines && importLines.length > 0) {
                    let importLine = importLines[0];
                    return importLine.substring('import '.length, importLine.length - 1);
                } else {
                    // 找不到import语句的java.lang包下的简名直接拼装java.lang包名
                    if (javaLangClassNames.includes(typeName)) {
                        return 'java.lang.' + typeName;
                    }

                    let key = ' class ' + simpleName + '<';
                    let index = code.indexOf(key);
                    if (index > 0) {
                        let genericTypeString = code.substring(index + key.length, code.indexOf('>', index));
                        let genericTypes = genericTypeString.split(',');
                        for (let genericType of genericTypes) {
                            let array = genericType.trim().split(' ');
                            if (array[0] === typeName) {
                                return typeName; // 泛型参数类型直接使用简名
                            }
                        }
                    }
                    if (packageName && !typeName.contains('.')) {
                        return packageName + '.' + typeName;
                    }
                }
            }
            return typeName;
        }

        const existModifier = function (modifiers, modifierName) {
            if (Array.isArray(modifiers)) {
                for (let modifier of modifiers) {
                    if (modifier.children && modifier.children[modifierName]) {
                        return true;
                    }
                }
            }
            return false;
        }

        const existPropertyMethod = function (classBodyElements, fieldSimpleType, fieldName) {
            let existsGetter = false;
            let existsSetter = false;
            for (let classBodyElement of classBodyElements) {
                if (classBodyElement.children.classMemberDeclaration) {
                    let methodElement = classBodyElement.children.classMemberDeclaration[0].children.methodDeclaration;
                    if (methodElement) {
                        methodElement = methodElement[0].children;
                        // 必须为public且非static
                        if (existModifier(methodElement.methodModifier, 'Public')
                            && !existModifier(methodElement.methodModifier, 'Static')) {
                            let methodHeaderElement = methodElement.methodHeader[0].children;
                            let methodResultElement = methodHeaderElement.result[0].children;
                            let methodName = methodHeaderElement.methodDeclarator[0].children.Identifier[0].image;
                            let parameterList = methodHeaderElement.methodDeclarator[0].children.formalParameterList;
                            let firstUpperCaseFieldName = fieldName.firstToUpperCase();
                            if ((fieldSimpleType !== 'boolean' && methodName === 'get' + firstUpperCaseFieldName)
                                || (fieldSimpleType === 'boolean' && methodName === 'is' + firstUpperCaseFieldName)) {
                                if (!methodResultElement.Void && !parameterList) { // getter方法没有参数
                                    let resultType = getTypeSimpleName(methodResultElement);
                                    if (resultType === fieldSimpleType) {
                                        existsGetter = true;
                                    }
                                }
                            } else if (methodName === 'set' + firstUpperCaseFieldName) {
                                if (methodResultElement.Void && parameterList?.length === 1) { // setter方法有一个参数
                                    let parameterElement = parameterList[0].children.formalParameter[0].children
                                        .variableParaRegularParameter[0].children;
                                    let argType = getTypeSimpleName(parameterElement);
                                    if (argType === fieldSimpleType) {
                                        existsSetter = true;
                                    }
                                }
                            }
                            if (existsGetter && existsSetter) {
                                return true;
                            }
                        }
                    }
                }
            }
            return false;
        }

        const getAnnotationValues = function (modifierElements) {
            let values = {};
            if (modifierElements) {
                for (let modifierElement of modifierElements) {
                    let annotationElement = modifierElement.children.annotation;
                    if (annotationElement) {
                        annotationElement = annotationElement[0].children;
                        if (annotationElement.At && annotationElement.At[0].image === '@') {
                            let annotationName = annotationElement.typeName[0].children.Identifier[0].image;
                            if (annotationName && annotationElement.elementValue) {
                                let annotationValue = annotationElement.elementValue[0].children
                                    .conditionalExpression[0].children
                                    .binaryExpression[0].children
                                    .unaryExpression[0].children
                                    .primary[0].children
                                    .primaryPrefix[0].children
                                    .literal[0].children
                                    .StringLiteral[0].image;
                                // 去掉两端的引号
                                if (annotationValue.startsWith('"') && annotationValue.endsWith('"')) {
                                    annotationValue = annotationValue.substring(1, annotationValue.length - 1);
                                }
                                values[annotationName] = annotationValue;
                            }
                        }
                    }
                }
            }
            return values;
        }

        const getFirstTypeParameter = function (classElement) {
            if (classElement.typeParameters) {
                return classElement.typeParameters[0].children.typeParameterList[0].children.typeParameter[0].children
                    .typeBound[0].children.classOrInterfaceType[0].children.classType[0].children.Identifier[0].image;
            } else if (classElement.classExtends) {
                let classTypeElement = classElement.classExtends[0].children.classType[0].children;
                if (classTypeElement.typeArguments) {
                    return classTypeElement.typeArguments[0].children.typeArgumentList[0].children
                        .typeArgument[0].children.referenceType[0].children.classOrInterfaceType[0].children
                        .classType[0].children.Identifier[0].image;
                }
            }
            return '';
        }

        const getConverterLogicType = function (classElement) {
            if (classElement.classImplements) {
                let interfaceTypeListElement = classElement.classImplements[0].children.interfaceTypeList;
                for (let interfaceTypeElement of interfaceTypeListElement) {
                    let classTypeElement = interfaceTypeElement.children.interfaceType[0].children.classType[0].children;
                    let interfaceSimpleName = classTypeElement.Identifier[0].image;
                    if (interfaceSimpleName === 'AttributeConverter') {
                        let referenceTypeElement = classTypeElement.typeArguments[0].children
                            .typeArgumentList[0].children.typeArgument[0].children.referenceType[0].children;
                        let logicType = '';
                        if (referenceTypeElement.classOrInterfaceType) {
                            logicType = referenceTypeElement.classOrInterfaceType[0].children.classType[0].children
                                .Identifier[0].image;
                        } else {
                            let integralTypeElement = referenceTypeElement.primitiveType[0].children.numericType[0].children.integralType[0].children;
                            if (integralTypeElement.Long) {
                                logicType = 'long';
                            } else if (integralTypeElement.Int) {
                                logicType = 'int';
                            } else {
                                console.warn(filePath + ':');
                                console.warn(integralTypeElement);
                            }
                        }
                        if (logicType) {
                            if (referenceTypeElement.dims) {
                                logicType += arraySuffix;
                            }
                            return logicType;
                        }
                    }
                }
            }
            return '';
        }

        if (predicate(packageName, simpleName, code)) {
            let cst;
            try {
                cst = parseJava(code);
            } catch (e) {
                console.error(filePath + '\n' + e);
                return false;
            }
            let classDeclaration = cst.children.ordinaryCompilationUnit[0].children
                .typeDeclaration[0].children.classDeclaration;
            if (classDeclaration) {
                let element = classDeclaration[0].children;

                let classModifiers = element.classModifier;
                if (!existModifier(classModifiers, 'Public')) {
                    return false;
                }
                let final = existModifier(classModifiers, 'Final');

                if (element.normalClassDeclaration) { // 普通类
                    let abstractClass = existModifier(classModifiers, 'Abstract');
                    let classElement = element.normalClassDeclaration[0].children;

                    let kind = TypeKind.CLASS;
                    let interfaceSimpleNames = getImplementInterfaceSimpleNames(classElement);
                    for (let interfaceSimpleName of interfaceSimpleNames) {
                        let interfaceName = getImportClassName(code, interfaceSimpleName);
                        if (interfaceName === 'org.truenewx.tnxjee.model.entity.unity.Unity') {
                            kind = TypeKind.UNITY;
                            break;
                        } else if (interfaceName === 'org.truenewx.tnxjee.model.entity.relation.Relation') {
                            kind = TypeKind.RELATION;
                            break;
                        } else if (interfaceName === 'org.truenewx.tnxjee.model.ValueModel') {
                            kind = TypeKind.VALUE;
                            break;
                        } else if (interfaceName.endsWith('.persistence.AttributeConverter')) {
                            kind = TypeKind.CONVERTER;
                            break;
                        }
                    }

                    let existsDefaultConstructor = false; // 是否存在默认构造函数
                    let validConstructorNum = 0; // 有效构造函数数量，public和protected
                    let invalidConstructorNum = 0; // 无效构造函数数量，private和默认级别
                    let existsPublicStaticBuilder = false; // 是否存在公开静态构建方法
                    // 转换器类寻找逻辑类型
                    let converterLogicType = '';
                    if (TypeKind.CONVERTER.equals(kind)) {
                        converterLogicType = getConverterLogicType(classElement);
                    }

                    let properties = [];
                    let classBodyElements = classElement.classBody[0].children.classBodyDeclaration;
                    if (classBodyElements) {
                        for (let classBodyElement of classBodyElements) {
                            let constructorDeclaration = classBodyElement.children.constructorDeclaration;
                            if (constructorDeclaration) {
                                let constructorModifier = constructorDeclaration[0].children.constructorModifier;
                                if (constructorModifier) {
                                    if (constructorModifier[0].children.Public) {
                                        validConstructorNum++;
                                        // 没有参数的public构造函数才是默认构造函数
                                        if (!constructorDeclaration[0].children.constructorDeclarator[0].children.formalParameterList) {
                                            existsDefaultConstructor = true;
                                        }
                                    }
                                    if (constructorModifier[0].children.Protected) {
                                        validConstructorNum++;
                                    }
                                    if (constructorModifier[0].children.Private) {
                                        invalidConstructorNum++;
                                    }
                                } else {
                                    invalidConstructorNum++;
                                }
                                continue;
                            }

                            let classMemberDeclarationElement = classBodyElement.children.classMemberDeclaration;
                            if (classMemberDeclarationElement) {
                                classMemberDeclarationElement = classMemberDeclarationElement[0].children;

                                let fieldDeclarationElement = classMemberDeclarationElement.fieldDeclaration;
                                if (fieldDeclarationElement) {
                                    fieldDeclarationElement = fieldDeclarationElement[0].children;

                                    let fieldName = fieldDeclarationElement.variableDeclaratorList[0].children
                                        .variableDeclarator[0].children.variableDeclaratorId[0].children.Identifier[0].image;
                                    if (fieldDeclarationElement.fieldModifier) {
                                        // 忽略静态字段
                                        if (fieldDeclarationElement.fieldModifier.some(
                                            fm => fm.children.Static)) {
                                            continue;
                                        }
                                    }
                                    let fieldSimpleType = getTypeSimpleName(fieldDeclarationElement);
                                    // 字段必须具有相应的public的Getter/Setter方法才视为属性
                                    if (existPropertyMethod(classBodyElements, fieldSimpleType, fieldName)) {
                                        let arrayed = fieldSimpleType.endsWith(arraySuffix);
                                        if (arrayed) {
                                            fieldSimpleType = fieldSimpleType.replace(/\[]/g, '');
                                        }
                                        let genericTypes = [];
                                        let index = fieldSimpleType.indexOf('<');
                                        if (index > 0 && fieldSimpleType.endsWith('>')) {
                                            let genericSimpleTypes = fieldSimpleType.substring(index + 1,
                                                fieldSimpleType.length - 1).split(',');
                                            for (let genericSimpleType of genericSimpleTypes) {
                                                let array = genericSimpleType.split(' ');
                                                let genericType = {};
                                                if (array.length === 1) {
                                                    genericType.simpleName = array[0];
                                                } else {
                                                    genericType.parameter = array[0];
                                                    genericType.extended = array[1] === 'extends';
                                                    genericType.simpleName = array[2];
                                                }
                                                let fullName = getImportClassName(code, genericType.simpleName);
                                                let dotIndex = fullName.lastIndexOf('.');
                                                if (dotIndex >= 0) {
                                                    genericType.packageName = fullName.substring(0, dotIndex);
                                                }
                                                genericTypes.push(genericType);
                                            }
                                            fieldSimpleType = fieldSimpleType.substring(0, index);
                                        }
                                        properties.push({
                                            name: fieldName,
                                            type: getImportClassName(code, fieldSimpleType),
                                            genericTypes: genericTypes,
                                            arrayed: arrayed,
                                            caption: getAnnotationValues(fieldDeclarationElement.fieldModifier).Caption,
                                        });
                                    }
                                }

                                let methodDeclarationElement = classMemberDeclarationElement.methodDeclaration;
                                if (methodDeclarationElement) {
                                    methodDeclarationElement = methodDeclarationElement[0].children;

                                    // 还没有找到静态构建方法，则寻找静态构建方法
                                    if (!existsPublicStaticBuilder) {
                                        let methodModifiers = methodDeclarationElement.methodModifier;
                                        if (existModifier(methodModifiers, 'Public')
                                            && existModifier(methodModifiers, 'Static')) {
                                            let unannType = methodDeclarationElement.methodHeader[0].children
                                                .result[0].children.unannType;
                                            if (unannType) {
                                                let unannReferenceType = unannType[0].children.unannReferenceType;
                                                if (unannReferenceType) {
                                                    let returnType = unannReferenceType[0].children
                                                        .unannClassOrInterfaceType[0].children.unannClassType[0].children
                                                        .Identifier[0].image;
                                                    if (returnType === simpleName) {
                                                        existsPublicStaticBuilder = true;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // 如果没有有效构造函数，也没有静态构建方法，但存在无效构造函数，则无效
                    if (validConstructorNum === 0 && !existsPublicStaticBuilder && invalidConstructorNum > 0) {
                        return false;
                    }
                    // 普通类，如果存在默认构建函数或不存在构造函数，且存在属性，则视为POJO
                    if (TypeKind.CLASS.equals(kind)) {
                        if ((existsDefaultConstructor || validConstructorNum + invalidConstructorNum === 0)
                            && properties.length) {
                            kind = TypeKind.PLAIN;
                        }
                    }

                    let superClassName = '';
                    if (classElement.classExtends) {
                        superClassName =
                            classElement.classExtends[0].children.classType[0].children.Identifier[0].image;
                        superClassName = getImportClassName(code, superClassName);
                        let superClass = lib.findClass(superClassName);
                        if (superClass) {
                            let superKind = superClass.getKind();
                            // 父类为转换器或自身类型为普通类时，父类的类型作为自身的类型
                            if (TypeKind.CONVERTER.equals(superKind) || TypeKind.CLASS.equals(kind)) {
                                kind = superKind;
                                // 转换器自身没有取得逻辑类型，则取父类的逻辑类型
                                if (TypeKind.CONVERTER.equals(superKind) && !converterLogicType) {
                                    converterLogicType = superClass.origin.logicType;
                                    // 如果父类逻辑类型为泛型参数，则子类尝试从泛型具化中获取逻辑类型
                                    if (converterLogicType === 'T') {
                                        converterLogicType = getFirstTypeParameter(classElement);
                                    }
                                }
                            }
                        }
                    }

                    let clazz;
                    if (kind.supports('entity')) {
                        clazz = new EntityClass(kind, packageName, simpleName);
                        clazz.properties = properties.map(p => EntityProperty.of(p));
                    } else if (TypeKind.VALUE.equals(kind)) {
                        clazz = new ValueClass(packageName, simpleName);
                        clazz.properties = properties.map(p => DomainProperty.of(p));
                    } else if (TypeKind.PLAIN.equals(kind)) {
                        clazz = new PlainClass(packageName, simpleName);
                        clazz.properties = properties.map(p => ClassProperty.of(p));
                    } else if (kind.supports('base')) {
                        clazz = new BaseClass(kind, packageName, simpleName);
                        if (classElement.typeParameters) {
                            let typeParameters = classElement.typeParameters[0].children.typeParameterList[0].children.typeParameter;
                            for (let typeParameter of typeParameters) {
                                let genericTypeParameter = typeParameter.children.typeIdentifier[0].children.Identifier[0].image;
                                clazz.declaredGenericTypes.push(GenericType.of({
                                    parameter: genericTypeParameter
                                }));
                            }
                        }
                    } else if (TypeKind.CONVERTER.equals(kind)) {
                        converterLogicType = converterLogicType || '';
                        let arrayed = converterLogicType.endsWith(arraySuffix);
                        converterLogicType = getImportClassName(code, converterLogicType);
                        if (arrayed) {
                            converterLogicType += arraySuffix;
                        }
                        clazz = new ConverterClass(packageName, simpleName, converterLogicType);
                    } else {
                        clazz = new BaseType(kind, packageName, simpleName);
                    }

                    if (!kind.supports('final')) {
                        clazz.final = final;
                    }
                    // 有abstractClass字段则赋值
                    if (clazz.abstractClass !== undefined) {
                        clazz.abstractClass = abstractClass;
                    }
                    // 有superClassId字段则赋值
                    if (clazz.superClassId !== undefined) {
                        // 依赖库中的类id与name相同
                        clazz.superClassId = superClassName;
                    }
                    clazz.caption = getAnnotationValues(classModifiers).Caption || '';

                    let dependencyClass = lib.pushClass(clazz);
                    dependencyClass.favoriteOrdinal = lib.getFavoriteOrdinal(dependencyClass.getName());
                    let declareIndex = code.indexOf(' class ' + simpleName);
                    dependencyClass.deprecated =
                        declareIndex > 0 && code.substring(0, declareIndex).contains('@Deprecated');
                } else if (element.enumDeclaration) { // 枚举类
                    let enumClass = new EnumClass(packageName, simpleName);
                    enumClass.caption = getAnnotationValues(classModifiers).Caption || '';
                    let enumChildren = element.enumDeclaration[0].children.enumBody[0].children;
                    let constantElementList = enumChildren.enumConstantList[0].children.enumConstant;
                    for (let constantElement of constantElementList) {
                        constantElement = constantElement.children;
                        let name = constantElement.Identifier[0].image;
                        let enumConstant = new EnumConstant(name);
                        let annotationValues = getAnnotationValues(constantElement.enumConstantModifier);
                        enumConstant.caption = annotationValues.Caption || '';
                        enumConstant.value = annotationValues.EnumConstantValue || '';
                        enumClass.constants.push(enumConstant);
                    }

                    let dependencyClass = lib.pushClass(enumClass);
                    let declareIndex = code.indexOf(' enum ' + simpleName);
                    dependencyClass.deprecated =
                        declareIndex > 0 && code.substring(0, declareIndex).contains('@Deprecated');
                }
            }
            return true;
        }
        return false;
    },

    loadByCodeZip(lib, zipPath, predicate, beforeInitialized, logStat = true) {
        if (lib.initialized === true) { // 已完成初始化
            if (typeof beforeInitialized === 'function') {
                beforeInitialized.call(this);
            }
        } else if (lib.initialized === false) { // 正在进行初始化
            // 等待500毫秒后重新执行
            setTimeout(() => {
                this.loadByCodeZip(lib, zipPath, predicate, beforeInitialized, logStat);
            }, 500);
        } else { // 尚未开始初始化
            lib.initialized = false; // 标记位正在初始化

            let _this = this;
            const parseFirstFile = function (codes, filePaths, stat, callback) {
                let filePath = filePaths.shift();
                if (filePath) {
                    setTimeout(() => {
                        try {
                            if (filePath.endsWith('.java') && !filePath.endsWith('package-info.java')) {
                                if (filePath.startsWith('/')) {
                                    filePath = filePath.substring(1);
                                }
                                let code = codes[filePath];
                                if (_this.loadJavaClass(lib, filePath, code, predicate)) {
                                    stat.parsedClassNum++;
                                }
                            }
                        } finally {
                            if (filePaths.length) {
                                parseFirstFile(codes, filePaths, stat, callback);
                            } else {
                                callback(stat);
                            }
                        }
                    }, 0);
                }
            }

            tnx.util.zip.readAll(zipPath).then(codes => {
                let filePaths = Object.keys(codes);
                if (logStat) {
                    console.info(`${zipPath} 开始解析，共 ${filePaths.length} 个文件...`);
                }
                parseFirstFile(codes, filePaths, {
                    startTime: new Date().getTime(),
                    parsedClassNum: 0,
                }, stat => {
                    lib.sortClasses();
                    if (logStat) {
                        let totalTime = new Date().getTime() - stat.startTime;
                        console.info(
                            `${zipPath} 共解析${stat.parsedClassNum}个文件，取得${lib.classes.length}个有效类，总耗时：${totalTime}ms`);
                    }
                    if (typeof beforeInitialized === 'function') {
                        beforeInitialized.call(this, codes);
                    }
                    lib.initialized = true;
                });
            });
        }
    },

    loadByCodeJar(lib, jarPath, predicate, beforeInitialized, logStat = true) {
        this.loadByCodeZip(lib, jarPath, predicate, codes => {
            if (codes) {
                let filePaths = Object.keys(codes);
                for (let filePath of filePaths) {
                    if (filePath.startsWith('META-INF/maven/') && filePath.endsWith('/pom.xml')) {
                        let pomXml = codes[filePath];
                        let mavenProject = tnx.util.xml.parse(pomXml);
                        mavenProject = mavenProject.project;
                        lib.groupId = mavenProject.groupId || mavenProject.parent.groupId || '';
                        lib.artifactId = mavenProject.artifactId;
                        lib.version = mavenProject.version || mavenProject.parent.version;
                        break;
                    }
                }
            }
            if (typeof beforeInitialized === 'function') {
                beforeInitialized.call(this);
            }
        }, logStat);
    },
}
